#ifdef WIN32

#include "WindowsWindow.h"


#include <iostream>
#include "Path/Path.h"
#include "Event/MouseEvent.h"
#include "Platform/WindowsPlatform.h"
#include "Platform/Windows/WindowsThread.h"
#include <Windows.h>
#include <vulkan/vulkan_win32.h>

uint64_t CWindowsWindow::GetWindowID() const
{
    return (uint64_t)Hwnd;
}

vk::SurfaceKHR CWindowsWindow::CreateVkSurfaceKHR(vk::Instance Instance)
{
    VkSurfaceKHR Surface;
    VkWin32SurfaceCreateInfoKHR CreateInfo = {};
    CreateInfo.sType = VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR;
    CreateInfo.hinstance = HInstance;
    CreateInfo.hwnd =(HWND) Hwnd;
    vkCreateWin32SurfaceKHR(Instance, &CreateInfo, nullptr, &Surface);
    return Surface;
}


SIntPoint CWindowsWindow::GetContentSize() const
{
    RECT Rect;
    GetClientRect((HWND)Hwnd, &Rect);
    return SIntPoint(Rect.right - Rect.left, Rect.bottom - Rect.top);
}

SIntPoint CWindowsWindow::GetWindowSize() const
{
    RECT Rect;
    GetWindowRect((HWND)Hwnd, &Rect);
    return SIntPoint(Rect.right - Rect.left, Rect.bottom - Rect.top);
}

void CWindowsWindow::SetWindowSize(SIntPoint InSize)
{
    SetWindowPos((HWND)Hwnd, nullptr, 0, 0, InSize.X, InSize.Y, SWP_NOMOVE | SWP_NOZORDER);
}

SIntPoint CWindowsWindow::GetWindowPosition() const
{
    RECT Rect;
    GetWindowRect((HWND)Hwnd, &Rect);
    return SIntPoint(Rect.left, Rect.top);
}

SIntPoint CWindowsWindow::GetContentPosition() const
{
    POINT Point;
    Point.x = 0;
    Point.y = 0;
    ClientToScreen((HWND)Hwnd, &Point);
    return SIntPoint(Point.x, Point.y);
}

void CWindowsWindow::SetWindowPosition(SIntPoint InPosition)
{
    SetWindowPos((HWND)Hwnd, nullptr, InPosition.X, InPosition.Y, 0, 0, SWP_NOSIZE | SWP_NOZORDER);
}

void CWindowsWindow::MoveToScreenCenter()
{
    //calculate center position
    int ScreenWidth = GetSystemMetrics(SM_CXSCREEN);
    int ScreenHeight = GetSystemMetrics(SM_CYSCREEN);

    int ScreenCenterX = ScreenWidth / 2;
    int ScreenCenterY = ScreenHeight / 2;

    auto WindowSize = GetWindowSize();

    int WindowPosX = ScreenCenterX - WindowSize.X / 2;
    int WindowPosY = ScreenCenterY - WindowSize.Y / 2;

    SetWindowPosition(SIntPoint(WindowPosX, WindowPosY));
}

void CWindowsWindow::SetWindowTitle(const CString &InTitle)
{
    auto Title16=InTitle.ToUtf16();
    SetWindowTextW((HWND)Hwnd, (wchar_t *)Title16.Data());
}

SRect CWindowsWindow::GetScreenPlacableArea()
{
    // get the work area, or the monitor area if no work area is defined
    HMONITOR hMonitor = MonitorFromWindow((HWND)Hwnd, MONITOR_DEFAULTTONEAREST);
    MONITORINFO monitorInfo;
    monitorInfo.cbSize = sizeof(MONITORINFO);
    GetMonitorInfo(hMonitor, &monitorInfo);
    RECT workArea = monitorInfo.rcWork;
    //RECT monitorArea = monitorInfo.rcMonitor;

    return SRect(workArea.left, workArea.top, workArea.right , workArea.bottom );

}

bool CWindowsWindow::IsMaximized() const
{
    return IsZoomed((HWND)Hwnd);
}

void CWindowsWindow::Maximize()
{
    ShowWindow((HWND)Hwnd, SW_MAXIMIZE);
}

bool CWindowsWindow::IsNormalSizeAndPosition() const
{
    return !IsMinimized() && !IsMaximized() && !IsFullScreen();
}

void CWindowsWindow::Restore()
{
    ShowWindow((HWND)Hwnd, SW_RESTORE);
}

bool CWindowsWindow::IsMinimized() const

{
    return IsIconic((HWND)Hwnd);
}

void CWindowsWindow::Minimize()
{
    ShowWindow((HWND)Hwnd, SW_MINIMIZE);
}

bool CWindowsWindow::IsFullScreen() const
{
    return bIsFullScreenMode;
}

void CWindowsWindow::FullScreen()
{
    //fullscreen window
    SetWindowPos((HWND)Hwnd, HWND_TOP, 0, 0, GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN), SWP_FRAMECHANGED);
    bIsFullScreenMode = true;
}

void CWindowsWindow::ShowBorder()
{
    bIsBorderVisible=true;

    //修改窗口样式，仅在窗口创建线程中调用有效
    CWindowsPlatform::Get()->WindowThread->
        SetWindowLongWithBlock(GetWindowID(), GWL_STYLE, WS_OVERLAPPEDWINDOW);
}

void CWindowsWindow::HideBorder()
{
    bIsBorderVisible=false;

    //修改窗口样式，仅在窗口创建线程中调用有效
    CWindowsPlatform::Get()->WindowThread->
        SetWindowLongWithBlock(GetWindowID(), GWL_STYLE, WS_POPUP);
}

bool CWindowsWindow::IsBorderVisible() const
{
    return bIsBorderVisible;
}


void CWindowsWindow::Show()
{
    ShowWindow((HWND)Hwnd, SW_SHOW);
}

void CWindowsWindow::Hide()
{
    ShowWindow((HWND)Hwnd, SW_HIDE);
}

bool CWindowsWindow::IsVisible() const
{
    return IsWindowVisible((HWND)Hwnd);
}

void CWindowsWindow::SetOpcity(float InOpacity)
{
    //set window opcity
    if (InOpacity < 1.0f)
    {
        SetWindowLong((HWND)Hwnd, GWL_EXSTYLE, GetWindowLong((HWND)Hwnd, GWL_EXSTYLE) | WS_EX_LAYERED);
        SetLayeredWindowAttributes((HWND)Hwnd, 0, (BYTE)(InOpacity * 255), LWA_ALPHA);
    }
    else
    {
        SetWindowLong((HWND)Hwnd, GWL_EXSTYLE, GetWindowLong((HWND)Hwnd, GWL_EXSTYLE) & ~WS_EX_LAYERED);
    }
}

void CWindowsWindow::EnableThisWindow(bool bEnable)
{
    EnableWindow((HWND)Hwnd, bEnable);
}

bool CWindowsWindow::IsThisWindowEnabled() const
{
    return IsWindowEnabled((HWND)Hwnd);
}

void CWindowsWindow::BringToFront()
{
    SetForegroundWindow((HWND)Hwnd);
}

void CWindowsWindow::HideInTaskbar()
{
    //hide window in taskbar
    SetWindowLong((HWND)Hwnd, GWL_EXSTYLE, GetWindowLong((HWND)Hwnd, GWL_EXSTYLE) | WS_EX_TOOLWINDOW);
}

#endif